package com.fiberhome.opticalbox.net;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

import android.text.TextUtils;

import com.fiberhome.opticalbox.net.bean.Parameter;
import com.fiberhome.opticalbox.net.bean.RequestBean;
import com.fiberhome.opticalbox.net.bean.ResponseBean;
import com.fiberhome.opticalbox.net.utils.Base64Code;
import com.fiberhome.opticalbox.net.utils.Util;
import com.fiberhome.opticalbox.utils.LogUtil;
import com.google.gson.Gson;

/**
 * @author tafiagu
 * @date 2013-5-9
 */
public class TcpClient {

	public static String sendAndReceiveTcpPacket(String serverAddress, int serverPort, String sendStr, int timeout, boolean useBase64)
			throws Exception {
		LogUtil.d("before encode request:\n" + sendStr);
		if (useBase64) {
			// 验证加密前和 加密后再解密的数据是否一致
			// Gson g = new Gson();
			// System.out.println("request wifi:" + sendStr);

			sendStr = encodeRequestParameter(sendStr);

			// Request encodeRep = g.fromJson(sendStr, Request.class);
			// Parameter decodeParam = g.fromJson(
			// new String(Base64Code.decode(encodeRep.Parameter)),
			// Parameter.class);
			//
			// System.out.println("request decode wifi:" +
			// g.toJson(decodeParam));
		}

		// LogUtils.d("after encode request:\n" + sendStr);

		Socket socket = null;
		String result = "";
		InetSocketAddress isa = null;
		ByteArrayOutputStream bos = null;
		OutputStream os = null;
		InputStream is = null;
		try {
			// socket = new Socket(serverAddress,serverPort);
			socket = new Socket();// 套接字的IP地址和端口号
			isa = new InetSocketAddress(serverAddress, serverPort);
			socket.connect(isa, timeout);
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (null != socket) {
			// socket.setReuseAddress(true);
			try {

				byte[] sendbytes = sendStr.getBytes("ISO-8859-1"); // 这个是为了中文乱码问题
				// byte[] sendbytes = sendStr.getBytes("UTF-8"); // 这个是为了中文乱码问题

				os = socket.getOutputStream();
				is = socket.getInputStream();

				bos = new ByteArrayOutputStream();
				bos.write(int2Byte(sendbytes.length));
				bos.write(sendbytes);
				os.write(bos.toByteArray());
				os.flush();

				byte[] buff = new byte[4];
				is.read(buff);
				// System.out.println("...." + byte2Int(buff));
				result = readInputstream(is);
//				LogUtils.d("before decode response:\n" + result);
				if (!TextUtils.isEmpty(result) && useBase64) {
					result = decodeResponseParameter(result);
				}
				LogUtil.d("after decode response:\n" + result);

			} catch (Exception e) {
				throw new Exception(e);
			} finally {
				try {
					if (bos != null) {
						bos.close();
						bos = null;
					}
					if (os != null) {
						os.close();
						os = null;
					}
					if (is != null) {
						is.close();
						is = null;
					}
					if (socket != null) {
						socket.close();// 记住一定要关闭这些输入，输出流和套接字
						socket = null;
					}

				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}

		return result;
	}

	public static class Request {
		String RPCMethod;

		String Plugin_Name;

		String Plugin_ID;

		String Version;

		String ID;

		String Parameter;
	}

	public static class Response {
		String Result;

		// String Parameter;
		String return_Parameter;

		String ID;
	}

	private static String readInputstream(InputStream in) {
		return Util.readInputstream(in);
	}

	private static String encodeRequestParameter(String sendStr) {
		// System.out.println("TcpClient encodeRequestParameter:" + sendStr);
		Gson g = new Gson();
		RequestBean request = g.fromJson(sendStr, RequestBean.class);
		String encodeParam = g.toJson(request.getParameter());
		encodeParam = Base64Code.byteArrayToBase64(encodeParam.getBytes());
		// LogUtils.d("after encode request:\n" + encodeParam);
		Request encodeReq = new Request();
		encodeReq.ID = "";
		encodeReq.Plugin_Name = request.getPlugin_Name();
		encodeReq.RPCMethod = request.getRPCMethod();
		encodeReq.Version = "";
		encodeReq.Parameter = encodeParam;
		return g.toJson(encodeReq);
	}

	public static String decodeResponseParameter(String result) {
		Gson g = new Gson();
		Response encodeRep = g.fromJson(result, Response.class);
		Parameter decodeParam = g.fromJson(new String(Base64Code.decode(encodeRep.return_Parameter)), Parameter.class);

		ResponseBean resp = new ResponseBean();
		resp.ID = encodeRep.ID;
		resp.Result = encodeRep.Result;
		// resp.Parameter = decodeParam;
		resp.return_Parameter = decodeParam;

		return g.toJson(resp);
	}

	public static byte[] int2Byte(int intValue) {

		byte[] b = new byte[4];
		for (int i = 0; i < 4; i++) {
			b[i] = (byte) (intValue >> 8 * (3 - i) & 0xFF);

		}

		return b;
	}

	public static int byte2Int(byte[] b) {
		int intValue = 0;
		for (int i = 0; i < b.length; i++) {
			intValue += (b[i] & 0xFF) << (8 * (3 - i));
		}
		return intValue;
	}

	public static byte[] combine(byte[] data1, byte[] data2) {
		byte[] data3 = new byte[data1.length + data2.length];

		System.arraycopy(data1, 0, data3, 0, data1.length);

		System.arraycopy(data2, 0, data3, data1.length, data2.length);

		return data3;
	}
}